/*
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
*/
package ai

import (
	"context"
	"errors"
	"fmt"
	"io"
	"time"

	"gitee.com/wfpeng/fanyi/pkg/config"
	"gitee.com/wfpeng/fanyi/pkg/prompt"

	"github.com/sashabaranov/go-openai"
)

// Client AI客户端接口
type Client interface {
	// Translate 翻译文本（非流式）
	// text 要翻译的文本
	// withOriginal 是否保留原文
	// 返回翻译后的文本和可能的错误
	Translate(text string, withOriginal bool) (string, error)

	// TranslateStream 流式翻译文本
	// text 要翻译的文本
	// withOriginal 是否保留原文
	// 返回流式翻译结果通道和错误通道
	TranslateStream(text string, withOriginal bool) (<-chan string, <-chan error)
}

// OpenAIClient 基于OpenAI兼容API的AI客户端
type OpenAIClient struct {
	client  *openai.Client
	config  *config.Config
	prompts *prompt.Prompt
}

// NewClient 创建新的AI客户端
// config 配置信息
// promptFile 可选的提示词文件路径
// 返回AI客户端接口实现
func NewClient(config *config.Config, promptFile string) (Client, error) {
	// 检查必要的配置
	if config.AI.APIKey == "" {
		return nil, errors.New("未设置API密钥，请在配置文件中设置ai.api_key或通过环境变量FANYI_AI_API_KEY设置")
	}

	// 创建OpenAI客户端配置
	clientConfig := openai.DefaultConfig(config.AI.APIKey)

	// 如果设置了自定义BaseURL，则使用自定义BaseURL
	if config.AI.BaseURL != "" {
		clientConfig.BaseURL = config.AI.BaseURL
	}

	// 创建OpenAI客户端
	client := openai.NewClientWithConfig(clientConfig)

	// 加载提示词
	var prompts *prompt.Prompt
	var err error

	// 如果指定了提示词文件，则从文件加载
	if promptFile != "" {
		prompts, err = prompt.LoadFromFile(promptFile)
		if err != nil {
			return nil, fmt.Errorf("加载提示词文件失败: %w", err)
		}
	} else {
		// 尝试在常见位置搜索提示词文件
		foundPromptFile := prompt.SearchPromptFile()
		if foundPromptFile != "" {
			prompts, err = prompt.LoadFromFile(foundPromptFile)
			if err != nil {
				// 如果加载失败，使用默认提示词
				fmt.Printf("加载提示词文件 %s 失败: %v，使用默认提示词\n", foundPromptFile, err)
				prompts = prompt.DefaultPrompt()
			} else {
				// fmt.Printf("已加载提示词文件: %s\n", foundPromptFile)
			}
		} else {
			// 如果没有找到提示词文件，则使用默认提示词
			prompts = prompt.DefaultPrompt()
		}
	}
	return &OpenAIClient{
		client:  client,
		config:  config,
		prompts: prompts,
	}, nil
}

// Translate 实现翻译功能（非流式）
// text 要翻译的文本
// withOriginal 是否保留原文
// 返回翻译后的文本和可能的错误
func (c *OpenAIClient) Translate(text string, withOriginal bool) (string, error) {
	// 选择系统提示词
	systemPrompt := c.prompts.TranslateOnly
	if withOriginal {
		systemPrompt = c.prompts.TranslateWithOriginal
	}

	// 创建上下文，设置超时
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()
	// fmt.Printf("systemPrompt: %s\n", systemPrompt)
	// 准备聊天请求
	req := openai.ChatCompletionRequest{
		Model: c.config.AI.Model,
		Messages: []openai.ChatCompletionMessage{
			{
				Role:    openai.ChatMessageRoleSystem,
				Content: systemPrompt,
			},
			{
				Role:    openai.ChatMessageRoleUser,
				Content: text,
			},
		},
		Temperature: 0.3, // 较低的温度使输出更加确定性
	}

	// 发送请求
	resp, err := c.client.CreateChatCompletion(ctx, req)
	if err != nil {
		return "", fmt.Errorf("调用AI服务失败: %w", err)
	}

	// 检查响应是否有内容
	if len(resp.Choices) == 0 {
		return "", errors.New("AI服务返回空响应")
	}

	// 返回翻译结果
	return resp.Choices[0].Message.Content, nil
}

// TranslateStream 实现流式翻译功能
// text 要翻译的文本
// withOriginal 是否保留原文
// 返回流式翻译结果通道和错误通道
func (c *OpenAIClient) TranslateStream(text string, withOriginal bool) (<-chan string, <-chan error) {
	resultChan := make(chan string, 100)
	errorChan := make(chan error, 1)

	go func() {
		defer close(resultChan)
		defer close(errorChan)

		// 选择系统提示词
		systemPrompt := c.prompts.TranslateOnly
		if withOriginal {
			systemPrompt = c.prompts.TranslateWithOriginal
		}

		// 创建上下文，设置超时
		ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
		defer cancel()

		// 准备流式聊天请求
		req := openai.ChatCompletionRequest{
			Model: c.config.AI.Model,
			Messages: []openai.ChatCompletionMessage{
				{
					Role:    openai.ChatMessageRoleSystem,
					Content: systemPrompt,
				},
				{
					Role:    openai.ChatMessageRoleUser,
					Content: text,
				},
			},
			Temperature: 0.3,  // 较低的温度使输出更加确定性
			Stream:      true, // 启用流式输出
		}

		// 创建流式请求
		stream, err := c.client.CreateChatCompletionStream(ctx, req)
		if err != nil {
			errorChan <- fmt.Errorf("创建流式AI服务失败: %w", err)
			return
		}
		defer stream.Close()

		// 读取流式响应
		for {
			response, err := stream.Recv()
			if err != nil {
				if errors.Is(err, io.EOF) {
					// 流结束，正常退出
					return
				}
				errorChan <- fmt.Errorf("接收流式响应失败: %w", err)
				return
			}

			// 检查响应是否有内容
			if len(response.Choices) > 0 && response.Choices[0].Delta.Content != "" {
				resultChan <- response.Choices[0].Delta.Content
			}
		}
	}()

	return resultChan, errorChan
}
